// webpack/scripts/start.js
//整个编译服务的启动入口
//包括以下功能----
//服务端代码的首次编译
//文件的监听
//前端代码的打包和 watch
//node服务的启动



//服务度代码编译完成后 启动node 服务
//服务代码每次编译后，重启node 服务


const {spawn} = require('child_process');//用于创建子进程
const constantCode = require('./constant');
const chalk = require('chalk');//为控制台输出的信息增加点色彩
const log = console.log;
const proConfig  = require('../../src/share/pro-config');

//node server port
const nodeServerPort = proConfig.nodeServerPort;


log(chalk.green('servers starting....'));



//前端代码构建 服务进程
/** 会用webpack监视client/app/index.js 有改变就打包到dist/static下*/
const feCodeWatchProcess = spawn('npm', ['run', 'fe:watch'], {
  stdio: 'inherit',

  /** ↓ https://nodejs.org/dist/latest-v12.x/docs/api/child_process.html#child_process_child_process_spawn_command_args_options*/
  shell: process.platform === 'win32' // ←不加的话,windows下会报错 Error: spawn npm ENOENT
});

//服务端代码监控和编译进程
/** node ./webpack/scripts/svr-code-watch.js
 * 即用webpack 监控 src/server/app/index.js
 * 每当被监控的文件发生变化后,会kill然后重启nodeServerProcess*/
const svrCodeWatchProcess = spawn('npm', ['run', 'svr:watch'],{shell: process.platform === 'win32'});

//node 服务进程
let nodeServerProcess=null;
//启动 node 服务
const startNodeServer = () => { //重启 node 服务
  nodeServerProcess && nodeServerProcess.kill();
  console.log('startNodeServer~~~~~');
  nodeServerProcess = spawn('node', ['./webpack/scripts/svr-dev-server.js'], {shell: process.platform === 'win32'});
  nodeServerProcess.stdout.on('data', print);
};

//控制台输出信息
function print(data) {
  let str = data.toString();

  if (str.indexOf(constantCode.SVRCODECOMPLETED) > -1/** ←参看 svr-code-watch.js, 简而言之就是在每次webpack重新编译后就会通知一次*/) { //服务端代码编译完成
    startNodeServer();//重启 node 服务
  } else {
    console.log(str);
  }
}

//监听服务端代码构建服务的对外输出  stdout 事件
svrCodeWatchProcess.stdout.on('data',print);

//杀掉子进程
const killChild = () => {
  svrCodeWatchProcess && svrCodeWatchProcess.kill();
  nodeServerProcess && nodeServerProcess.kill();
  feCodeWatchProcess && feCodeWatchProcess.kill();
};

//主进程关闭退出子进程
process.on('close', (code) => {
    console.log('main process  close', code);
    killChild();
});
//主进程关闭退出子进程
process.on('exit', (code) => {
    console.log('main process  exit', code);
    killChild();
});

//非正常退出情况
process.on('SIGINT'/** ←SIGINT 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出，用于通知前台进程组终止进程。*/, function () {
    svrCodeWatchProcess.stdin.write('exit'/** ←参看 svr-code-watch.js, 简而言之就是svrCodeWatchProcess那边的监听接受到exit后就会退出进程*/, (error) => {
        console.log('svr code watcher process exit!');
    });
    killChild();
});
